import { defineStore } from 'pinia'
import { openDB } from 'idb'
import Compressor from 'compressorjs'
import { ref } from 'vue'

// 数据库名称和版本
const DB_NAME = 'shan-tu'
const DB_VERSION = 1

// 最大存储空间（2GB）
const MAX_STORAGE_SIZE = 2 * 1024 * 1024 * 1024

// 初始化 IndexDB
const initDB = async () => {
    return openDB(DB_NAME, DB_VERSION, {
        upgrade(db) {
            // 表情包存储
            if (!db.objectStoreNames.contains('emojis')) {
                const emojiStore = db.createObjectStore('emojis', { keyPath: 'id', autoIncrement: true })
                emojiStore.createIndex('tags', 'tags', { multiEntry: true })
                emojiStore.createIndex('favorite', 'favorite')
                emojiStore.createIndex('type', 'type')
            }

            // 标签存储
            if (!db.objectStoreNames.contains('tags')) {
                const tagStore = db.createObjectStore('tags', { keyPath: 'id', autoIncrement: true })
                tagStore.createIndex('name', 'name', { unique: true })
            }
        }
    })
}

// 压缩图片
const compressImage = (file) => {
    return new Promise((resolve, reject) => {
        if (!(file instanceof Blob)) {
            reject(new Error('The first argument must be a File or Blob object.'))
            return
        }
        new Compressor(file, {
            quality: 0.8,
            maxWidth: 800,
            maxHeight: 800,
            convertSize: 200000, // 200KB
            success(result) {
                resolve(result)
            },
            error(err) {
                reject(err)
            }
        })
    })
}

// 将 Blob 转换为 Base64
const blobToBase64 = (blob) => {
    return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.onloadend = () => resolve(reader.result)
        reader.onerror = reject
        reader.readAsDataURL(blob)
    })
}

// 将 Base64 转换为 Blob
const base64ToBlob = (base64) => {
    const parts = base64.split(';base64,')
    const contentType = parts[0].split(':')[1]
    const raw = window.atob(parts[1])
    const rawLength = raw.length
    const uInt8Array = new Uint8Array(rawLength)

    for (let i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i)
    }

    return new Blob([uInt8Array], { type: contentType })
}

// 获取所有标签
const getAllTags = async function () {
    await this.ensureInitialized()
    const db = await openDB(DB_NAME)
    const tx = db.transaction(['tags', 'emojis'], 'readonly')
    const tagStore = tx.objectStore('tags')
    const emojiStore = tx.objectStore('emojis')

    const tags = await tagStore.getAll()
    const emojis = await emojiStore.getAll()

    // 计算每个标签下的表情数量
    return tags.map(tag => ({
        ...tag,
        count: emojis.filter(emoji => emoji.tags && emoji.tags.includes(tag.name)).length
    }))
}

// 添加标签
const addTag = async function (name) {
    await this.ensureInitialized()
    const db = await openDB(DB_NAME)
    const tx = db.transaction('tags', 'readwrite')
    const store = tx.objectStore('tags')

    // 检查标签是否已存在
    const existingTag = await store.index('name').get(name)
    if (existingTag) {
        throw new Error('标签已存在')
    }

    await store.add({
        id: Date.now().toString(),
        name,
        createdAt: new Date().toISOString()
    })
}

// 更新标签
const updateTag = async function (id, newName) {
    await this.ensureInitialized()
    const db = await openDB(DB_NAME)
    const tx = db.transaction(['tags', 'emojis'], 'readwrite')
    const tagStore = tx.objectStore('tags')
    const emojiStore = tx.objectStore('emojis')

    // 获取原标签
    const tag = await tagStore.get(id)
    if (!tag) {
        throw new Error('标签不存在')
    }

    // 检查新名称是否已存在
    if (tag.name !== newName) {
        const existingTag = await tagStore.index('name').get(newName)
        if (existingTag) {
            throw new Error('标签名称已存在')
        }
    }

    // 更新所有使用该标签的表情
    const emojis = await emojiStore.getAll()
    for (const emoji of emojis) {
        if (emoji.tags && emoji.tags.includes(tag.name)) {
            const newTags = emoji.tags.map(t => t === tag.name ? newName : t)
            await emojiStore.put({ ...emoji, tags: newTags })
        }
    }

    // 更新标签
    await tagStore.put({ ...tag, name: newName })
}

// 删除标签
const deleteTag = async function (id) {
    await this.ensureInitialized()
    const db = await openDB(DB_NAME)
    const tx = db.transaction(['tags', 'emojis'], 'readwrite')
    const tagStore = tx.objectStore('tags')
    const emojiStore = tx.objectStore('emojis')

    // 获取标签
    const tag = await tagStore.get(id)
    if (!tag) {
        throw new Error('标签不存在')
    }

    // 从所有表情中移除该标签
    const emojis = await emojiStore.getAll()
    for (const emoji of emojis) {
        if (emoji.tags && emoji.tags.includes(tag.name)) {
            const newTags = emoji.tags.filter(t => t !== tag.name)
            await emojiStore.put({ ...emoji, tags: newTags })
        }
    }

    // 删除标签
    await tagStore.delete(id)
}

export const useEmojiStore = defineStore('emoji', () => {
    const db = ref(null)
    const initialized = ref(false)
    const allEmojis = ref([])
    const favoriteEmojis = ref([])
    const storageUsage = ref(0)

    // 计算存储使用情况
    const calculateStorageUsage = async () => {
        try {
            // 获取所有表情的大小总和
            const tx = db.value.transaction('emojis', 'readonly')
            const store = tx.objectStore('emojis')
            const emojis = await store.getAll()

            // 计算总大小（字节）
            const totalSize = emojis.reduce((sum, emoji) => {
                // 如果是 base64 数据，计算实际大小
                if (emoji.data && typeof emoji.data === 'string') {
                    // base64 字符串实际大小约为字符串长度的 0.75
                    const base64Length = emoji.data.replace(/^data:image\/\w+;base64,/, '').length
                    return sum + Math.round(base64Length * 0.75)
                }
                // 如果有 size 属性，直接使用
                if (emoji.size) {
                    return sum + emoji.size
                }
                return sum
            }, 0)

            // 计算使用百分比（转换为MB进行显示）
            const totalMB = totalSize / (1024 * 1024)
            const maxMB = MAX_STORAGE_SIZE / (1024 * 1024)
            storageUsage.value = Math.round((totalSize / MAX_STORAGE_SIZE) * 10000) / 100

            console.log('当前存储使用情况：', {
                总大小: totalSize + ' 字节',
                总大小MB: totalMB.toFixed(2) + ' MB',
                最大限制: maxMB + ' MB',
                使用率: storageUsage.value + '%'
            })

            return storageUsage.value
        } catch (error) {
            console.error('计算存储使用失败:', error)
            return 0
        }
    }

    const init = async () => {
        if (initialized.value) return

        try {
            db.value = await initDB()
            await loadEmojis()
            await loadTags()
            await calculateStorageUsage()
            initialized.value = true
        } catch (error) {
            console.error('初始化数据库失败:', error)
            throw error
        }
    }

    const ensureInitialized = async () => {
        if (!initialized.value) {
            await init()
        }
    }

    const loadEmojis = async () => {
        try {
            const tx = db.value.transaction('emojis', 'readonly')
            const store = tx.objectStore('emojis')
            allEmojis.value = await store.getAll()
            // 更新收藏表情
            favoriteEmojis.value = allEmojis.value.filter(emoji => emoji.favorite)
            // 重新计算存储使用
            await calculateStorageUsage()
        } catch (error) {
            console.error('加载表情包失败:', error)
            throw error
        }
    }

    const loadTags = async () => {
        try {
            const tx = db.value.transaction('tags', 'readonly')
            const store = tx.objectStore('tags')
            const tags = await store.getAll()
            return tags
        } catch (error) {
            console.error('加载标签失败:', error)
            throw error
        }
    }

    const saveEmoji = async ({ data, url, type, name, size, tags = [] }) => {
        try {
            // 检查存储空间
            const currentUsage = await calculateStorageUsage()
            const newSize = size || 0
            const projectedUsage = Math.round(((currentUsage * MAX_STORAGE_SIZE / 100) + newSize) / MAX_STORAGE_SIZE * 100)

            if (projectedUsage > 100) {
                throw new Error('存储空间不足，请清理后再试')
            }

            let finalData
            if (type === 'url') {
                finalData = { url, type, tags, favorite: false, createdAt: new Date() }
            } else {
                let file
                if (data instanceof File || data instanceof Blob) {
                    file = data instanceof File ? data : new File([data], name || 'image.png', { type: data.type })
                } else if (typeof data === 'string' && data.startsWith('data:')) {
                    const blob = base64ToBlob(data)
                    file = new File([blob], name || 'image.png', { type: blob.type })
                } else {
                    throw new Error('Invalid image data')
                }

                let compressedFile
                try {
                    compressedFile = await compressImage(file)
                } catch (error) {
                    console.warn('图片压缩失败，使用原始文件:', error)
                    compressedFile = file
                }

                const base64 = await blobToBase64(compressedFile)

                finalData = {
                    data: base64,
                    type: 'file',
                    name: name || file.name || 'image.png',
                    tags,
                    favorite: false,
                    createdAt: new Date(),
                    size: compressedFile.size
                }
            }

            const tx = db.value.transaction(['emojis', 'tags'], 'readwrite')
            const emojiStore = tx.objectStore('emojis')
            const id = await emojiStore.add(finalData)

            // 更新内存中的数据
            allEmojis.value.push({ id, ...finalData })

            // 如果有标签，确保它们存在于标签列表中
            if (tags && tags.length > 0) {
                const tagStore = tx.objectStore('tags')
                for (const tagName of tags) {
                    const existingTag = await tagStore.index('name').get(tagName)
                    if (!existingTag) {
                        await tagStore.add({
                            id: Date.now().toString(),
                            name: tagName,
                            createdAt: new Date().toISOString()
                        })
                    }
                }
            }

            // 保存后更新存储使用
            await calculateStorageUsage()

            return id
        } catch (error) {
            console.error('保存表情包失败:', error)
            throw error
        }
    }

    const saveTags = async (newTags) => {
        try {
            const tx = db.value.transaction('tags', 'readwrite')
            const store = tx.objectStore('tags')

            for (const tag of newTags) {
                if (!allEmojis.value.find(t => t.name === tag)) {
                    await store.add({ name: tag })
                    allEmojis.value.push({ name: tag })
                }
            }
        } catch (error) {
            console.error('保存标签失败:', error)
        }
    }

    const updateEmoji = async (id, updates) => {
        try {
            const tx = db.value.transaction('emojis', 'readwrite')
            const store = tx.objectStore('emojis')
            const emoji = await store.get(id)

            if (!emoji) throw new Error('表情包不存在')

            const updatedEmoji = { ...emoji, ...updates }
            await store.put(updatedEmoji)

            // 更新内存中的数据
            const index = allEmojis.value.findIndex(e => e.id === id)
            if (index !== -1) {
                allEmojis.value[index] = updatedEmoji

                // 如果是收藏状态变更，更新收藏列表
                if ('favorite' in updates) {
                    if (updates.favorite) {
                        // 添加到收藏
                        if (!favoriteEmojis.value.find(e => e.id === id)) {
                            favoriteEmojis.value.push(updatedEmoji)
                        }
                    } else {
                        // 从收藏中移除
                        favoriteEmojis.value = favoriteEmojis.value.filter(e => e.id !== id)
                    }
                }
            }

            // 如果有新标签，保存它们
            if (updates.tags) {
                await saveTags(updates.tags)
            }
        } catch (error) {
            console.error('更新表情包失败:', error)
            throw error
        }
    }

    const deleteEmoji = async (id) => {
        try {
            const tx = db.value.transaction('emojis', 'readwrite')
            const store = tx.objectStore('emojis')
            await store.delete(id)

            // 更新内存中的数据
            allEmojis.value = allEmojis.value.filter(emoji => emoji.id !== id)

            // 删除后更新存储使用
            await calculateStorageUsage()
        } catch (error) {
            console.error('删除表情包失败:', error)
            throw error
        }
    }

    const toggleFavorite = async (id) => {
        const emoji = allEmojis.value.find(e => e.id === id)
        if (emoji) {
            const newFavorite = !emoji.favorite
            await updateEmoji(id, { favorite: newFavorite })
        }
    }

    return {
        db,
        initialized,
        allEmojis,
        favoriteEmojis,
        storageUsage,
        calculateStorageUsage,
        init,
        ensureInitialized,
        loadEmojis,
        loadTags,
        saveEmoji,
        saveTags,
        updateEmoji,
        deleteEmoji,
        toggleFavorite,
        getAllTags,
        addTag,
        updateTag,
        deleteTag
    }
}) 